package huffman;

import huffman.HuffmanIn.Item;
import huffman.HuffmanIn.Node;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class HuffmanHeader {
	public Integer NumByteVal = 0;
	public Integer MaxEncValSize = 0;
	public Node root;
	public Item items[] = new Item[256];
	public HuffmanHeader(List<Item> itemslist) {
		for(Item i: itemslist) {
			items[i.character & 0xFF] = i;
		}
		Collections.sort(itemslist, Collections.reverseOrder());
		Item i1, i2;
		while(itemslist.size() >= 2) {
			i1 =	Collections.min(itemslist);
			itemslist.remove(i1);
			
			i2 =	Collections.min(itemslist);
			itemslist.remove(i2);
			
			itemslist.add(new Node(null, i1.occurance + i2.occurance, i1, i2));
		}
		
		root = (Node)itemslist.get(0);
		iterate(root, "");
//		
//		for(int i = 0;i < 256; i++) {
//			if(items[i] != null) {
//				System.out.println(items[i].character + "\t" + items[i].occurance + "\t" + items[i].value);
//			}
//		}
	}
//	
	private void iterate(Item n, String v) {
		n.value = v;
		if(n.value.length() > MaxEncValSize) {
			MaxEncValSize = n.value.length();
		}
		if(n instanceof Node) {
			Node no = (Node) n;
			iterate(no.leftChild, n.value + "0");
			iterate(no.rightChild,  n.value + "1");
		} 
		
		if(n.character != null) {
			items[n.character & 0xFF] = n;
			NumByteVal++;
		}
		
	}
	
	public void write(DataOutputStreamEx dos) throws IOException, InterruptedException {
		dos.writeInt(NumByteVal);
		dos.writeInt(MaxEncValSize);
		
		writeItem(root, dos);
	}
	
	private void writeItem(Item n, DataOutputStreamEx dos) throws IOException, InterruptedException {
		if(n instanceof Node) {
			Node no = (Node) n;
			writeItem(no.leftChild, dos);
			writeItem(no.rightChild, dos);
		}  
		if(n.character != null) {
			dos.writeByte(n.character);
			dos.writeInt(n.occurance);
		}
	}
	
	
	private HuffmanHeader() { }
	
	public static HuffmanHeader readFromCompressedFile(DataInputStreamEx dis) throws IOException {
		HuffmanHeader h;


		int NumByteVal = dis.readInt();
		int MaxEncValSize = dis.readInt();
		List<Item> itekms = new ArrayList<Item>();
		for(int i = 0;i < NumByteVal;i++) {
			byte b = dis.readByte();
			int ir = dis.readInt();
			itekms.add(new Item(b, ir));
		}

		h = new HuffmanHeader(itekms);
		
		return h;
	}
	
	public static void setValue(Item n, String v) {
		n.value = v;
		if(n instanceof Node) {
			Node no = (Node) n;
			setValue(no.leftChild, n.value + "0");
			setValue(no.rightChild,  n.value + "1");
		} 		
	}
}
